package com.dcrzl.gazgmh.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
//import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

@Slf4j
public class SysUtils {
    /**
     * 验证手机号
     *
     * @param str
     * @return
     * @throws PatternSyntaxException
     */
    public static boolean checkChinaPhoneLegal(String str) throws PatternSyntaxException {
        // ^ 匹配输入字符串开始的位置
        // \d 匹配一个或多个数字，其中 \ 要转义，所以是 \\d
        // $ 匹配输入字符串结尾的位置
        String regExp = "(^1[3|4|5|6|7|8|9]\\d{9}$)|(^09\\d{8}$)";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(str);
        return m.matches();
    }

    public static boolean checkEmail(String email) {// 验证邮箱的正则表达式
        String format = "\\p{Alpha}\\w{2,15}[@][a-z0-9]{3,}[.]\\p{Lower}{2,}";
        //p{Alpha}:内容是必选的，和字母字符[\p{Lower}\p{Upper}]等价。如：200896@163.com不是合法的。
        //w{2,15}: 2~15个[a-zA-Z_0-9]字符；w{}内容是必选的。 如：dyh@152.com是合法的。
        //[a-z0-9]{3,}：至少三个[a-z0-9]字符,[]内的是必选的；如：dyh200896@16.com是不合法的。
        //[.]:'.'号时必选的； 如：dyh200896@163com是不合法的。
        //p{Lower}{2,}小写字母，两个以上。如：dyh200896@163.c是不合法的。
        return email.matches(format);
    }

    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "" );
    }

    public static Date getDate(Date date) {
        return dateAddDay(date, 1);
    }

    public static Date dateAddDay(Date date, int day) {
        Date date1 = nowDate(date);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);//设置起时间
        cal.add(Calendar.DATE, day);//增加一天
        Date date2 = cal.getTime();
        return date2;
    }


    public static Date nowDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd" );
        String time = sdf.format(date);
        Date date1 = null;
        try {
            date1 = sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date1;
    }

    /**
     * 描述:获取下一个月的第一天.
     *
     * @return
     */
    public static Date getPerFirstDayOfMonth() {
        SimpleDateFormat dft = new SimpleDateFormat("yyyyMMdd" );
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        Date date = calendar.getTime();
        String format = dft.format(date);
        try {
            return dft.parse(format);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取月份最后一天
     *
     * @param
     * @return
     * @throws ParseException
     */
    public static Date getMaxMonthDate(Date date) {
        SimpleDateFormat dft = new SimpleDateFormat("yyyyMMdd" );
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        String dateStr = dft.format(calendar.getTime());
        dateStr = dateStr + "235959";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss" );
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取当年的最后一天
     *
     * @param
     * @return
     */
    public static Date getCurrYearLast() {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        Date date = getYearLast(currentYear);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd" );
        String format = sdf.format(date);
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss" );
        format = format + "235959";
        try {
            return sdf1.parse(format);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取某年最后一天日期
     *
     * @param year 年份
     * @return Date
     */
    public static Date getYearLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTime();
    }

    public static JSONObject sendPost(String url, Map<String, Object> map, RestTemplate restTemplate) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8" );
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        String jsonParam = JSON.toJSONString(map);
        HttpEntity<String> formEntity = new HttpEntity<>(jsonParam, headers);
        JSONObject result = restTemplate.postForEntity(url, formEntity, JSONObject.class).getBody();
        assert result != null;
        log.info(result.toString());
        return result;
    }

//    public static InputStream sendBufferPost(String url, Map<String, Object> map, RestTemplate restTemplate) {
//        HttpHeaders headers = new HttpHeaders();
//        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
//        headers.setContentType(type);
//        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
//        String jsonParam = JSON.toJSONString(map);
//        HttpEntity<String> formEntity = new HttpEntity<>(jsonParam, headers);
//        ResponseEntity<byte[]> entity =
//                restTemplate.exchange(url, HttpMethod.POST,formEntity, byte[].class);
//        byte[] result = entity.getBody();
//        return new ByteArrayInputStream(result);
//    }

    public static byte[] sendBufferPost(String url, Map<String, Object> map, RestTemplate restTemplate) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8" );
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        String jsonParam = JSON.toJSONString(map);
        HttpEntity<String> formEntity = new HttpEntity<>(jsonParam, headers);
        ResponseEntity<byte[]> entity =
                restTemplate.exchange(url, HttpMethod.POST, formEntity, byte[].class);
        return entity.getBody();
    }

    /**
     * 计算地球上任意两点(经纬度)距离
     *
     * @param long1 第一点经度
     * @param lat1  第一点纬度
     * @param long2 第二点经度
     * @param lat2  第二点纬度
     * @return 返回距离 单位：米
     */
    public static double distanceByLongNLat(double long1, double lat1, double long2, double lat2) {
        double a, b, R;
        R = 6378137;//地球半径
        lat1 = lat1 * Math.PI / 180.0;
        lat2 = lat2 * Math.PI / 180.0;
        a = lat1 - lat2;
        b = (long1 - long2) * Math.PI / 180.0;
        double d;
        double sa2, sb2;
        sa2 = Math.sin(a / 2.0);
        sb2 = Math.sin(b / 2.0);
        d = 2 * R * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
        return d;
    }

    /**
     * 添加水印
     *
     * @param inputStream
     * @param mark
     * @return
     */
    public static InputStream addMark(InputStream inputStream, String mark, Integer rgb, Float alpha, Integer fontSize, Integer degree) {

        if (Objects.isNull(rgb)) {
            rgb = 0xffffff;
        }
        if (Objects.isNull(alpha)) {
            alpha = 1F;
        }
        if (Objects.isNull(fontSize)) {
            fontSize = 60;
        }

        String[] waterMarkContents = mark.split("\\|\\|" );
        // 用来调整水印的间距
        int space = 20;
        //将读取流转化为图片对象
        Image srcImg = null;
        try {
            srcImg = ImageIO.read(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //获取图片的宽
        int srcImgWidth = srcImg.getWidth(null);
        //获取图片的高
        int srcImgHeight = srcImg.getHeight(null);
        System.out.println("图片的宽:" + srcImgWidth);
        System.out.println("图片的高:" + srcImgHeight);

        BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
        // 加水印
        //创建画笔
        Graphics2D g = bufImg.createGraphics();
        //设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        //srcImg 为上面获取到的原始图片的图片对象
        g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);

        //设置水印旋转
        if (null != degree) {
            g.rotate(Math.toRadians(degree),
                    (double) bufImg.getWidth() / 2,
                    (double) bufImg.getHeight() / 2);
        }

        //根据图片的背景设置水印颜色

        g.setColor(new Color(rgb));
        g.setComposite(AlphaComposite
                .getInstance(AlphaComposite.SRC_OVER, alpha));
        //设置字体  画笔字体样式为微软雅黑，加粗，文字大小为60pt
        g.setFont(new Font("微软雅黑", Font.BOLD, fontSize));


        java.util.List<String> waterMarkContentList = new ArrayList<>();
// 将换行后的文字放入新的集合
        for (String markContent : waterMarkContents) {
            // 单字符长度
            int tempCharLen = 0;
            // 单行字符总长度临时计算
            int tempLineLen = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < markContent.length(); i++) {
                char tempChar = markContent.charAt(i);
                tempCharLen = getCharLen(tempChar, g);
                tempLineLen += tempCharLen;
                // 文字长度大于图片宽度-2*间距-字体大小
                if (tempLineLen > srcImgWidth - space * 2 - tempCharLen) {
                    // 长度已经满一行
                    waterMarkContentList.add(sb.toString());
                    // 清空内容,重新追加
                    sb.delete(0, sb.length());
                    tempLineLen = 0;
                }
                // 追加字符
                sb.append(tempChar);
            }
            waterMarkContentList.add(sb.toString());
        }

        // 绘制水印
        int tempY = fontSize + space;
        for (int i = 0; i < waterMarkContentList.size(); i++) {
            String s = waterMarkContentList.get(i);
            //左上角
//                g.drawString(s, space, i * tempY + 3 * space);
            //右下角
            g.drawString(s, space, srcImgHeight - (waterMarkContentList.size() - i) * tempY + space);

//            g.drawString(s, space, (srcImgHeight - (waterMarkContentList.size() - i) * (tempY*2))/2 + space);

            //设置水印的坐标
//            int x = (srcImgWidth - getWatermarkLength(mark, g)) / 2;
//            int y = srcImgHeight / 2;
            //画出水印 第一个参数是水印内容，第二个参数是x轴坐标，第三个参数是y轴坐标
//            g.drawString(s, x, y);
        }
        g.dispose();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufImg, "jpg", baos);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return new ByteArrayInputStream(baos.toByteArray());
    }

    /**
     * 获取水印文字的长度
     *
     * @param waterMarkContent
     * @param g
     * @return
     */
    private static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }

    private static int getCharLen(char c, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charWidth(c);
    }


//    public static InputStream base64ToInputStream(String base64Img) throws IOException, TranscoderException {
//        //获取base64
//        String data = base64Img.substring(base64Img.indexOf("," ) + 1);//去除前缀
//        BASE64Decoder decoder = new BASE64Decoder();
//        //转码
//        byte[] b = decoder.decodeBuffer(data);
//        for (int i = 0; i < b.length; ++i) {
//            if (b[i] < 0) {//调整异常数据
//                b[i] += 256;
//            }
//        }
////            String res = new String(b, "UTF-8");
//////            log.info(res);
//        return convertToPng(b);
//    }

    /**
     * 将svgCode转换成png文件，直接输出到流中
     *
     * @throws TranscoderException 异常
     * @throws IOException         io异常
     */
    public static InputStream convertToPng(byte[] bytes)
            throws TranscoderException, IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            PNGTranscoder t = new PNGTranscoder();
            TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(bytes));
            TranscoderOutput output = new TranscoderOutput(outputStream);
            t.transcode(input, output);
            outputStream.flush();
            return new ByteArrayInputStream(outputStream.toByteArray());
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        try {
            InputStream inputStream = new FileInputStream("D:\\小爱文件资料\\3cc5b15448ff026ffe20f144991b84d.jpg" );
            InputStream inputStream1 = addMark(inputStream, "河北省石家庄市正定县X009,秦家庄傻激" +
                    "果||" +
                    "2023-03-23 10:29:12", 0xff0000, 0.6F, 30, null);
            String tarImgPath = "D:\\小爱文件资料\\测试.jpg";
            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
            byte[] buf = new byte[1024];
            int le = -1;
            while ((le = inputStream1.read(buf)) != -1) {
                outImgStream.write(buf, 0, le);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }


}
